package Backend.Algorithmen;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import GUI.Cell;

public class Kurskal extends SuperAlgo {

	private ArrayList<Cell> cells = new ArrayList<Cell>();

	private Random rand = new Random();

	public Kurskal(String name) {
		super(name);
	}

	@Override
	public void start(boolean slow) {
		cells.clear();

		int id = 0;
		for (int i = 0; i < grid.length; i++) {
			for (int j = 0; j < grid[i].length; j++) {
				grid[i][j].initialGroupSet(id);
				cells.add(grid[i][j]);
				id++;
			}
		}

		long start = System.currentTimeMillis();

		while (cells.size() > 0 && isRunning()) {

			Cell me = cells.get(rand.nextInt(cells.size()));
			Cell neighbour = getNeighbour(me);

			if (neighbour == null) {
				cells.remove(me);
				double t = ((available_cells - cells.size()) / ((float) (available_cells / 100)));
				setStatus((int) t);
				continue;
			}

			updateSet(me, neighbour);

			breaktTheWalls(me, neighbour);



			if (slow) {
				try {
					Thread.currentThread().sleep(getDelay());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		setTime(System.currentTimeMillis() - start);
		grid[0][0].setLeft(false);
		grid[rand.nextInt(ycount)][xcount-1].setRight(false);

	}

	private Cell getNeighbour(Cell c) {

		ArrayList<Cell> tmp = new ArrayList<Cell>();
		Cell neighbour = null;

		if ((c.getPosy() - 1) > -1) {
			neighbour = grid[c.getPosy() - 1][c.getPosx()];
			if (neighbour.getGroup() != c.getGroup())
				tmp.add(neighbour);
		}
		if ((c.getPosx() + 1) < xcount) {
			neighbour = grid[c.getPosy()][c.getPosx() + 1];
			if (neighbour.getGroup() != c.getGroup())
				tmp.add(neighbour);
		}
		if ((c.getPosy() + 1) < ycount) {
			neighbour = grid[c.getPosy() + 1][c.getPosx()];
			if (neighbour.getGroup() != c.getGroup())
				tmp.add(neighbour);
		}
		if ((c.getPosx() - 1) > -1) {
			neighbour = grid[c.getPosy()][c.getPosx() - 1];
			if (neighbour.getGroup() != c.getGroup())
				tmp.add(neighbour);
		}
		if (tmp.size() == 0)
			return null;
		if (tmp.size() == 1)
			return tmp.get(0);

		return tmp.get(rand.nextInt(tmp.size() - 1));
	}

	private void updateSet(Cell me, Cell neighbour) {
	
		if (!me.groupChanged() && !neighbour.groupChanged()) {
			grid[neighbour.getPosy()][neighbour.getPosx()].setGroup(me.getGroup());
			grid[me.getPosy()][me.getPosx()].setGroup(me.getGroup());

		} else if (me.groupChanged() && !neighbour.groupChanged()) {
			grid[neighbour.getPosy()][neighbour.getPosx()].setGroup(me.getGroup());

		} else if (!me.groupChanged() && neighbour.groupChanged()) {
			grid[me.getPosy()][me.getPosx()].setGroup(neighbour.getGroup());

		} else if (neighbour.groupChanged() && me.groupChanged()) {
			int replace = me.getGroup();
			int search = neighbour.getGroup();
			for (int i = 0; i < grid.length; i++) {
				for (int j = 0; j < grid[i].length; j++) {

					if (grid[i][j].getGroup() == search) {
						grid[i][j].setGroup(replace);
					}

				}
			}
		}
	}

	private void breaktTheWalls(Cell c1, Cell c2) {
		int border = c1.position(c2);

		switch (border) {
		case Cell.TOP:
			c1.setTop(false);
			c2.setBottom(false);
			break;
		case Cell.BOTTOM:
			c2.setTop(false);
			c1.setBottom(false);
			break;
		case Cell.RIGHT:
			c1.setRight(false);
			c2.setLeft(false);
			break;
		case Cell.LEFT:
			c2.setRight(false);
			c1.setLeft(false);
			break;
		}
	}

}
